package com.dev.widget.ui;



import com.dev.utils.LogUtils;
import com.dev.utils.app.SizeUtils;
import com.dev.utils.app.TextViewUtils;
import dev.widget.ResourceTable;
import ohos.agp.components.Attr;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Arc;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;
import ohos.global.resource.NotExistException;
import ohos.global.resource.WrongTypeException;



import java.io.IOException;
import java.util.Optional;

public class LoadProgressBar extends Component {

    private  static  final String TAG = LoadProgressBar.class.getSimpleName();
    private DrawTask task = new DrawTask() {
        @Override
        public void onDraw(Component component, Canvas canvas) {
            boolean isDrawNumber = mIsCanvasNumber;
            // 防止没有设置样式
            if (mProgressStyle == null) mProgressStyle = ProgressStyle.RINGS;
            // 属于默认类型
            if (mProgressStyle == ProgressStyle.RINGS) { // 绘制圆环
                float centre = getWidth() / 2; // 获取圆心的 x 坐标
                float radius = (centre - mOuterRingWidth / 2); // 圆环的半径
                mPaint.setColor(new Color(mOuterRingColor)); // 设置圆环的颜色
                mPaint.setStyle(Paint.Style.STROKE_STYLE); // 设置空心
                mPaint.setStrokeWidth(mOuterRingWidth); // 设置圆环的宽度
                mPaint.setAntiAlias(true); // 消除锯齿
                canvas.drawCircle(centre, centre, radius, mPaint); // 画出圆环

                // 设置进度是实心还是空心
                mPaint.setStrokeWidth(mOuterRingWidth); // 设置圆环的宽度
                mPaint.setStyle(Paint.Style.STROKE_STYLE); // 设置空心
                mPaint.setColor(new Color(mProgressColor)); // 设置进度的颜色
                mPaint.setAntiAlias(true); // 消除锯齿
                // 用于定义的圆弧的形状和大小的界限
                RectFloat oval = new RectFloat(centre - radius, centre - radius, centre + radius, centre + radius);
                // 根据进度画圆弧 ( 0 从右边开始 , 270 从上边开始 )
                //canvas.drawArc(oval, 270, 360 * mProgress / mMax, false, mPaint);
                Arc arc = new Arc(270, 360 * mProgress / mMax, false);
                canvas.drawArc(oval, arc,mPaint);

            } else if (mProgressStyle == ProgressStyle.FAN_SHAPED) { // 绘制扇形
                int centre = getWidth() / 2; // 获取圆心的 x 坐标
                int radius = centre; // 扇形的半径
                mPaint.setStrokeWidth(centre); // 设置扇形的宽度
                mPaint.setStyle(Paint.Style.FILL_STYLE); // 设置实心
                mPaint.setColor(new Color(mProgressColor));  // 设置进度的颜色
                mPaint.setAntiAlias(true);  // 消除锯齿
                // 绘制扇形
                RectFloat ovalBorder = new RectFloat(centre - radius, centre - radius, centre + radius, centre + radius);
               // canvas.drawArc(ovalBorder, 270, 360 * mProgress / mMax, true, mPaint);
                Arc arc = new Arc(270, 360 * mProgress / mMax, true);
                canvas.drawArc(ovalBorder, arc, mPaint);
            } else if (mProgressStyle == ProgressStyle.ARC_FAN_SHAPED) {

                // 判断是否没设置内圈宽度, 如果没有设置, 则设置为贴着外圈
                if (mInsideCircleWidth <= 0) {
                    // 设置内圈大小
                    mInsideCircleWidth = getWidth() - mOuterRingWidth * 2;
                }
                // 绘制圆环 + 扇形
                float centre = getWidth() / 2; // 获取圆心的 x 坐标
                float radius = (centre - mOuterRingWidth / 2); // 圆环的半径
                // 设置进度是实心还是空心
                mPaint.setStrokeWidth(mOuterRingWidth); // 设置圆环的宽度
                mPaint.setStyle(Paint.Style.STROKE_STYLE); // 设置空心
                mPaint.setColor(new Color(mOuterRingColor));  // 设置进度的颜色
                mPaint.setAntiAlias(true);  // 消除锯齿
                // 绘制圆外环
                RectFloat ovalBorder = new RectFloat(centre - radius, centre - radius, centre + radius, centre + radius);
                Arc arc = new Arc( 270, 360, false);
                canvas.drawArc(ovalBorder, arc, mPaint);
                // 绘制椭圆
                mPaint.setStrokeWidth(mInsideCircleWidth); // 设置圆的宽度
                mPaint.setStyle(Paint.Style.FILL_STYLE); // 设置实心
                mPaint.setColor(new Color(mProgressColor));  // 设置进度的颜色
                // 获取圆心的 x 坐标
                centre = (mInsideCircleWidth / 2);
                // 圆的半径
                radius = centre;
                // 边距
                float margin = (getWidth() - mInsideCircleWidth) / 2;
                // 绘制扇形
                RectFloat oval = new RectFloat(margin + centre - radius, margin + centre - radius,
                        margin + centre + radius, margin + centre + radius);
                Arc arc1 = new Arc(270, (360 * mProgress) / mMax, true);
                canvas.drawArc(oval, arc1, mPaint);  // 根据进度画圆弧
            } else if (mProgressStyle == ProgressStyle.NUMBER) {
                // 绘制的内容
                String progressText = (mProgress * 100 / mMax) + "%";
                // 判断是否存在计算的字体大小
                if (mNumberTextSize <= 0) {
                    int tempWidth = getWidth();
                    // 计算字体大小
                    mNumberTextSize = TextViewUtils.reckonTextSizeByWidth(tempWidth, mTextPaint,
                                    SizeUtils.pxConvertSp(tempWidth, canvas.getDeviceDensity(getContext())), "100%");
                }
                // 绘制进度文本
                drawProgressText(canvas, mNumberTextSize, mNumberTextColor, progressText);
                // 已经绘制数字, 则不绘制
                isDrawNumber = false;
            }
            // 判断是否绘制内容
            if (isDrawNumber) {
                // 设置实心
                mPaint.setStyle(Paint.Style.FILL_STYLE);
                // 判断样式
                switch (mProgressStyle) {
                    case RINGS: // 圆环
                    case FAN_SHAPED: // 扇形
                        // 判断是否存在计算的字体大小
                        if (mNumberTextSize <= 0) {
                            int tempWidth = getWidth() / 3 * 2;
                            // 计算字体大小
                            mNumberTextSize = TextViewUtils.reckonTextSizeByWidth(tempWidth, mTextPaint,
                                    SizeUtils.pxConvertSp(tempWidth,canvas.getDeviceDensity(getContext())), "100%");
                        }
                        // 绘制进度文本
                        drawProgressText(canvas, mNumberTextSize, mNumberTextColor, (mProgress * 100 / mMax) + "%");
                        break;
                    case ARC_FAN_SHAPED:
                        // 判断是否存在计算的字体大小
                        if (mNumberTextSize <= 0) {
                            // 计算字体大小
                            if (mInsideCircleWidth < 0f) {
                                int tempWidth = getWidth() / 3 * 2;
                                // 计算字体大小
                                mNumberTextSize = TextViewUtils.reckonTextSizeByWidth(tempWidth, mTextPaint,
                                        SizeUtils.pxConvertSp(tempWidth, canvas.getDeviceDensity(getContext())), "100%");
                            } else {
                                int tempWidth = (int) mInsideCircleWidth / 3 * 2;
                                // 计算字体大小
                                mNumberTextSize = TextViewUtils.reckonTextSizeByWidth(tempWidth, mTextPaint,
                                        SizeUtils.pxConvertSp(tempWidth, canvas.getDeviceDensity(getContext())), "100%");
                            }
                        }
                        // 绘制进度文本
                        drawProgressText(canvas, mNumberTextSize, mNumberTextColor, (mProgress * 100 / mMax) + "%");
                        break;
                }
            }
        }
    };

    public LoadProgressBar(Context context) throws NotExistException, WrongTypeException, IOException {
        super(context);
        initAttrs(context, null);
    }

    public LoadProgressBar(Context context, AttrSet attrSet) throws NotExistException, WrongTypeException, IOException {
        super(context, attrSet);
        initAttrs(context, attrSet);
    }

    public LoadProgressBar(Context context, AttrSet attrSet, String styleName) throws NotExistException, WrongTypeException, IOException {
        super(context, attrSet, styleName);
        initAttrs(context, attrSet);
    }

    public LoadProgressBar(Context context, AttrSet attrSet, int resId) {
        super(context, attrSet, resId);

        try {
            initAttrs(context, attrSet);
        } catch (NotExistException e) {
            e.printStackTrace();
        } catch (WrongTypeException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    // 画笔
    private Paint mPaint;
    // 字体画笔
    private Paint mTextPaint = new Paint();
    // 最大进度
    private       int           mMax            = 100;
    // 当前进度
    private       int           mProgress       = 0;
    // 进度条样式
    private       ProgressStyle mProgressStyle  = ProgressStyle.RINGS;
    // 进度条颜色
    private       int           mProgressColor;
    // 外环进度条颜色
    private       int           mOuterRingColor;
    // 内环进度条宽度
    private       float         mInsideCircleWidth;
    // 外环进度条宽度
    private       float         mOuterRingWidth;
    // 是否绘制数字
    private       boolean       mIsCanvasNumber = false;
    // 绘制的字体大小
    private       float         mNumberTextSize;
    // 绘制的数字颜色
    private       int           mNumberTextColor;



    /**
     * 初始化
     * @param context {@link Context}
     * @param attrs   {@link AttrSet}
     */
    private void initAttrs(
            Context context,
            AttrSet attrs
    )  throws NotExistException, WrongTypeException, IOException{

        LogUtils.error(TAG, "initAttrs");
        init(); // 默认初始化配置
        if (context != null && attrs != null) {
            mIsCanvasNumber = getBoolean(attrs.getAttr(getResourceManager().getElement(ResourceTable.String_dev_canvasNumber).getString()), mIsCanvasNumber);
            mProgressColor = getColor(attrs.getAttr(getResourceManager().getElement(ResourceTable.String_dev_progressColor).getString()), mProgressColor);
            mOuterRingColor = getColor(attrs.getAttr(getResourceManager().getElement(ResourceTable.String_dev_outerRingColor).getString()), mOuterRingColor);
            mInsideCircleWidth = getColor(attrs.getAttr(getResourceManager().getElement(ResourceTable.String_dev_insideCircleWidth).getString()), (int) mInsideCircleWidth);
            mOuterRingWidth = getDismension(attrs.getAttr(getResourceManager().getElement(ResourceTable.String_dev_outerRingWidth).getString()), (int) mOuterRingWidth);
            mNumberTextSize = getDismension(attrs.getAttr(getResourceManager().getElement(ResourceTable.String_dev_numberTextSize).getString()), (int) mNumberTextSize);
            mNumberTextColor = getColor(attrs.getAttr(getResourceManager().getElement(ResourceTable.String_dev_numberTextColor).getString()), (int) mNumberTextColor);
            int progressStyle = getEnum(attrs.getAttr(getResourceManager().getElement(ResourceTable.String_dev_progressStyle).getString()), 0);

            switch (progressStyle) {
                case 0:
                    mProgressStyle = ProgressStyle.RINGS;
                    break;
                case 1:
                    mProgressStyle = ProgressStyle.FAN_SHAPED;
                    break;
                case 2:
                    mProgressStyle = ProgressStyle.ARC_FAN_SHAPED;
                    break;
                case 3:
                    mProgressStyle = ProgressStyle.NUMBER;
                    break;
                default:
                    mProgressStyle = ProgressStyle.RINGS;
                    break;
            }
        }
        }

    private int getInteger(Optional<Attr> attr, int defaultValue) throws NotExistException, WrongTypeException, IOException {
        if (attr.isPresent()) {
            return attr.get().getIntegerValue();
        } else {
            return defaultValue;
        }
    }
    private int getEnum(Optional<Attr> attr, int defaultValue) throws NotExistException, WrongTypeException, IOException {
        if (attr.isPresent()) {
            String str =  attr.get().getStringValue();
            if ("rings".equals(str)) {
                return 0;
            } else if ("fan_shaped".equals(str)) {
                return 1;
            } else if ("arc_fan_shaped".equals(str)) {
                return 2;
            } else if ("number".equals(str)) {
                return 3;
            }
        }
            return defaultValue;

    }

    /**
     * 初始化方法
     * @return {@link LoadProgressBar}
     */
    private LoadProgressBar init() {
        // 初始化画笔
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        // 设置进度颜色值 ( 白色 )
        mProgressColor = Color.rgb(255, 255, 255); // Color.WHITE
        // 设置外环颜色
        mOuterRingColor = Color.argb(30, 255, 255, 255);
        // 设置外环进度条的宽度
        mOuterRingWidth = SizeUtils.dipConvertPx(4.0f);
        // 设置绘制的数字颜色
        mNumberTextColor = Color.BLACK.getValue();
        // 初始化处理
        mNumberTextSize = 0;
        mInsideCircleWidth = 0;
        mIsCanvasNumber = false;
        addDrawTask(task);
        return this;
    }
    /**
     * 绘制进度文本
     * @param canvas       {@link Canvas}
     * @param textSize     字体大小
     * @param textColor    字体颜色
     * @param progressText 绘制文本
     */
    private void drawProgressText(
            Canvas canvas,
            float textSize,
            int textColor,
            String progressText
    ) {
        drawProgressText(canvas, getWidth(), getHeight(), textSize, textColor, progressText);
    }

    /**
     * 绘制进度文本
     * @param canvas       {@link Canvas}
     * @param width        对应的宽度 ( 居中使用 )
     * @param height       对应的高度 ( 居中使用 )
     * @param textSize     字体大小
     * @param textColor    字体颜色
     * @param progressText 绘制文本
     */
    private void drawProgressText(
            Canvas canvas,
            int width,
            int height,
            float textSize,
            int textColor,
            String progressText
    ) {
        mPaint.setColor(new Color(textColor));  // 设置进度的颜色
        mPaint.setTextSize((int) textSize); // 设置字体大小
        // 获取字体高度
        Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
        // 获取字体内容宽度
        float tWidth = mPaint.measureText(progressText);
        // 计算字体内容高度
        float fontTotalHeight = fontMetrics.bottom - fontMetrics.top;
        float offY            = fontTotalHeight / 2 - fontMetrics.bottom;
        // 设置左、上边距
        float x = (width - tWidth) / 2;
        float y = height / 2 + offY;
        // 绘制内容
        canvas.drawText(mPaint,progressText, x, y);
    }


    private int getColor(Optional<Attr> attr, int defaultValue) {
        if (attr.isPresent()) {
            return attr.get().getColorValue().getValue();
        } else {
            return defaultValue;
        }
    }


    private int getDismension(Optional<Attr> attr, int defaultValue) {

        if (attr.isPresent()) {
           return attr.get().getDimensionValue();
        } else  {
            return defaultValue;
        }

    }
    private float getFloat(Optional<Attr> attr, float defaultValue) throws NotExistException, WrongTypeException, IOException {
        if (attr.isPresent()) {
            return attr.get().getFloatValue();
        } else {
            return defaultValue;
        }
    }

    private Boolean getBoolean(Optional<Attr> attr, boolean defaultValue) throws NotExistException, WrongTypeException, IOException {
        //isPresent = false 表示不存在返回默认  = true 表示有输入，使用输入的数据为
        if (attr.isPresent()) {
            return attr.get().getBoolValue();
        } else {
            return defaultValue;
        }
    }
    // ===============
    // = 对外公开方法 =
    // ===============

    /**
     * 重置参数
     * @return {@link LoadProgressBar}
     */
    public LoadProgressBar reset() {
        return init();
    }

    /**
     * 获取最大值
     * @return 最大值
     */
    public synchronized int getMax() {
        return mMax;
    }

    /**
     * 设置最大值
     * @param max 最大值
     * @return {@link LoadProgressBar}
     */
    public synchronized LoadProgressBar setMax(int max) {
        if (max <= 0) throw new IllegalArgumentException("max not less than 0");
        this.mMax = max;
        return this;
    }

    /**
     * 获取当前进度
     * @return 当前进度
     */
    public synchronized int getProgress() {
        return mProgress;
    }

    /**
     * 设置当前进度
     * @param progress 当前进度
     * @return {@link LoadProgressBar}
     */
    public synchronized LoadProgressBar setProgress(int progress) {
        if (progress < 0) throw new IllegalArgumentException("progress not less than 0");
        if (progress > mMax) {
            progress = mMax;
        }
        if (progress <= mMax) {
            this.mProgress = progress;
            invalidate();
        }
        return this;
    }

    /**
     * 获取进度条颜色
     * @return 进度条颜色
     */
    public int getProgressColor() {
        return mProgressColor;
    }

    /**
     * 设置进度条颜色
     * @param progressColor 进度条颜色
     * @return {@link LoadProgressBar}
     */
    public LoadProgressBar setProgressColor( int progressColor) {
        this.mProgressColor = progressColor;
        return this;
    }

    /**
     * 获取外环进度条颜色
     * @return 外环进度条颜色
     */
    public int getOuterRingColor() {
        return mOuterRingColor;
    }

    /**
     * 设置外环进度条颜色
     * @param outerRingColor 外环进度条颜色
     * @return {@link LoadProgressBar}
     */
    public LoadProgressBar setOuterRingColor(int outerRingColor) {
        this.mOuterRingColor = outerRingColor;
        return this;
    }

    /**
     * 获取内环进度条宽度
     * @return 内环进度条宽度
     */
    public float getInsideCircleWidth() {
        return mInsideCircleWidth;
    }

    /**
     * 设置内环进度条宽度
     * @param insideCircleWidth 内环进度条宽度
     * @return {@link LoadProgressBar}
     */
    public LoadProgressBar setInsideCircleWidth(float insideCircleWidth) {
        this.mInsideCircleWidth = Math.abs(insideCircleWidth);
        return this;
    }

    /**
     * 获取外环进度条宽度
     * @return 外环进度条宽度
     */
    public float getOuterRingWidth() {
        return mOuterRingWidth;
    }

    /**
     * 设置外环进度条宽度
     * @param outerRingWidth 外环进度条宽度
     * @return {@link LoadProgressBar}
     */
    public LoadProgressBar setOuterRingWidth(float outerRingWidth) {
        this.mOuterRingWidth = Math.abs(outerRingWidth);
        return this;
    }

    /**
     * 是否绘制数字
     * @return {@code true} yes, {@code false} no
     */
    public boolean isCanvasNumber() {
        return mIsCanvasNumber;
    }

    /**
     * 设置是否绘制数字
     * @param canvasNumber {@code true} yes, {@code false} no
     * @return {@link LoadProgressBar}
     */
    public LoadProgressBar setCanvasNumber(boolean canvasNumber) {
        this.mIsCanvasNumber = canvasNumber;
        return this;
    }

    /**
     * 获取绘制的字体大小
     * @return 绘制的字体大小
     */
    public float getNumberTextSize() {
        return mNumberTextSize;
    }

    /**
     * 设置绘制的字体大小
     * @param numberTextSize 绘制的字体大小
     * @return {@link LoadProgressBar}
     */
    public LoadProgressBar setNumberTextSize(float numberTextSize) {
        this.mNumberTextSize = numberTextSize;
        return this;
    }

    /**
     * 获取绘制的数字颜色
     * @return 绘制的数字颜色
     */
    public int getNumberTextColor() {
        return mNumberTextColor;
    }

    /**
     * 设置绘制的数字颜色
     * @param numberTextColor 绘制的数字颜色
     * @return {@link LoadProgressBar}
     */
    public LoadProgressBar setNumberTextColor(int numberTextColor) {
        this.mNumberTextColor = numberTextColor;
        return this;
    }

    /**
     * 获取进度条样式
     * @return {@link ProgressStyle}
     */
    public ProgressStyle getProgressStyle() {
        return mProgressStyle;
    }

    /**
     * 设置进度条样式
     * @param progressStyle {@link ProgressStyle}
     * @return {@link LoadProgressBar}
     */
    public LoadProgressBar setProgressStyle(ProgressStyle progressStyle) {
        this.mProgressStyle = (progressStyle == null) ? ProgressStyle.RINGS : progressStyle;
        return this;
    }

        /**
         * detail: 进度条样式
         * @author Ttt
         */
    public enum ProgressStyle {

        // 圆环
        RINGS,

        // 扇形进度样式
        FAN_SHAPED,

        // 圆环扇形进度样式
        ARC_FAN_SHAPED,

        // 绘制数字
        NUMBER
    }

}
